package com.springboot.last_experiment.securityutil;

import com.alibaba.fastjson.JSON;
import com.springboot.last_experiment.entity.Admin;
import com.springboot.last_experiment.voutils.ResultVOUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired
  private AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> authenticationDetailsSource;

  protected Log log = LogFactory.getLog(this.getClass());

  @Autowired
  private AuthenticationProvider authenticationProvider;

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {

    auth.authenticationProvider(authenticationProvider);
  }

  //定义登陆成功返回信息
  private class AjaxAuthSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {

      //User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
//      log.info("商户[" + SecurityContextHolder.getContext().getAuthentication().getPrincipal() +"]登陆成功！");
      Admin admin = (Admin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
      System.out.println(admin);
      response.setContentType("application/json;charset=utf-8");
      PrintWriter out = response.getWriter();
      out.write(JSON.toJSONString(ResultVOUtil.success(admin)));
      out.flush();
      out.close();
    }
  }

  //定义登陆失败返回信息(用户名或密码错误走这里)
  private class AjaxAuthFailHandler extends SimpleUrlAuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {

      response.setContentType("application/json;charset=utf-8");
//      response.setStatus(HttpStatus.UNAUTHORIZED.value());
      PrintWriter out = response.getWriter();
      out.write(JSON.toJSONString(ResultVOUtil.error(500,"用户名或密码错误")));
      out.flush();
      out.close();
    }
  }

  //定义异常返回信息(没登录直接访问需要权限的页面就会走这里)
  public class UnauthorizedEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {

      response.sendRedirect("/login");
//      response.setContentType("application/json;charset=utf-8");
////      response.setStatus(HttpStatus.UNAUTHORIZED.value());
//      PrintWriter out = response.getWriter();
//      out.write(JSON.toJSONString(ResultVOUtil.error(401,"请先登录")));
//      out.flush();
//      out.close();
    }

  }

  //定义登出成功返回信息
  private class AjaxLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler  {

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
                                Authentication authentication) throws IOException, ServletException {
      response.setContentType("application/json;charset=utf-8");
      PrintWriter out = response.getWriter();
      out.write(JSON.toJSONString(ResultVOUtil.success(null)));
      out.flush();
      out.close();
    }
  }

//  前端资源设置不拦截
  @Override
  public void configure(WebSecurity web) {
    web.ignoring().antMatchers("/**/*.css", "/**/*.html", "/img/**", "/**/*.png", "/**/*.js", "/**/*.ico");
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
        .exceptionHandling().authenticationEntryPoint(new UnauthorizedEntryPoint())
        .and()
        .csrf().disable()
        .authorizeRequests()
        .antMatchers("/login", "/loginAuthen", "/", "/user/*", "/health", "/healths/byOpenid/*", "/user").permitAll()    //放行页面,登录相关+微信小程序相关
        .anyRequest().authenticated()
        .and().formLogin().loginPage("/login")
        .successHandler(new AjaxAuthSuccessHandler())
        .failureHandler(new AjaxAuthFailHandler())
        .loginProcessingUrl("/admin/login")
        .authenticationDetailsSource(authenticationDetailsSource)
        .and()
        .logout().logoutSuccessHandler(new AjaxLogoutSuccessHandler())
        .logoutUrl("/admin/logout");
  }
}
